import datetime
import json
from typing import Any, List, Dict

from django.http import HttpResponse, HttpRequest
from django.db.models import QuerySet
from ninja import Field, ModelSchema, NinjaAPI, Query, Router, Schema
from ninja.types import DictStrAny
from ninja.pagination import paginate, PaginationBase


class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime("%Y-%m-%d %H:%M:%S")
        else:
            return json.JSONEncoder.default(self, obj)


class Response(HttpResponse):

    def __init__(self, data=None, msg='success', code=200, success=True, *args, **kwargs):
        std_data = {
            "code": code,
            "results": data,
            "message": msg,
            "success": success
        }
        data = json.dumps(std_data, cls=DateEncoder)
        super().__init__(data, *args, **kwargs)


class MyNinjaAPI(NinjaAPI):
    def create_response(
            self, request: HttpRequest, data: Any, *, status: int = 200, code: int = 200, msg: str = "success",
            success: bool = True,
            temporal_response: HttpResponse = None,
    ) -> HttpResponse:
        """ 统一控制返回的数据格式 """
        std_data = {
            "code": code,
            "data": data,
            "message": msg,
            "success": success
        }
        content = self.renderer.render(request, std_data, response_status=status)
        content_type = "{}; charset={}".format(
            self.renderer.media_type, self.renderer.charset
        )

        return HttpResponse(content, status=status, content_type=content_type)


def format_error_msg(error_lst: List[Dict]) -> str:
    """ 将 pydantic 返回的错误信息转换下格式返回 """
    err_msg_lst = []
    for error in error_lst:
        print(error)
        err_key = error['loc'][-1]
        msg = error['msg']
        err_msg = f"{err_key}: {msg}"
        err_msg_lst.append(err_msg)
    msg = "。".join(err_msg_lst)
    return msg


class MyPagination(PaginationBase):

    items_attribute: str = "results"

    class Input(Schema):
        pageSize: int = Field(10, gt=0, title='每页数量')
        page: int = Field(1, gt=-1, title='第几页')

    class Output(Schema):
        results: List[Any]
        total: int

    def paginate_queryset(
            self,
            queryset: QuerySet,
            pagination: Input,
            **params: DictStrAny,
    ) -> Any:
        offset = pagination.pageSize * (pagination.page - 1)
        limit: int = pagination.pageSize
        return {
            "page": offset,
            "limit": limit,
            "results": queryset[offset: offset + limit],
            "total": self._items_count(queryset),
        }
